<script lang="ts" setup>
import { ref, reactive, onUpdated, onMounted } from 'vue'
import { NCard, NInput, NInputGroup, NIcon, NScrollbar, NButton, NTree, NSpace, NCheckbox, NPopover } from 'naive-ui'
import type { TreeOption } from 'naive-ui'
import http from '@/tools/http'
import { ReloadOutlined, CloseOutlined } from '@vicons/antd'
import { useOrgStore } from '@/stores/orgStore'
import { useConfigStore } from '@/stores/configStore'

import type { UserInfo } from '../model'

type SelectorUserInfo = UserInfo & {
    isChecked: boolean
}

const props = defineProps(["value", "title"])
const emits = defineEmits(["cancel", "update:value"])

const orgStore = useOrgStore()
const configStore = useConfigStore()

const orgSearchPattern = ref<string>("")

let timer: NodeJS.Timeout

const userList = reactive<SelectorUserInfo[]>([])
const sourceUserList = reactive<SelectorUserInfo[]>([])
const targetUserList = reactive<SelectorUserInfo[]>([])
const userSearchResList = reactive<SelectorUserInfo[]>([])

onMounted(() => {
    initTargetUserList()
})

onUpdated(() => {
})

function treeNodeClicked(info: { option: TreeOption }) {
    return {
        onClick: () => {
            getOrgUserInfo(info.option.value as string)
        }
    }
}

function selectAll() {
    for (let i = 0; i < sourceUserList.length; i++) {
        sourceAddUser(sourceUserList[i].userId)
    }
}

function clear() {
    targetUserList.length = 0
    for (let i = 0; i < sourceUserList.length; i++) {
        sourceUserList[i].isChecked = false
    }
    for (let i = 0; i < userList.length; i++) {
        userList[i].isChecked = false
    }
}

function sourceAddUser(userId: string) {
    let addFlag = true
    for (let i = 0; i < sourceUserList.length; i++) {
        if (sourceUserList[i].userId === userId) {
            if (sourceUserList[i].isChecked === false) {
                sourceUserList[i].isChecked = true
                targetUserList.push({ ...sourceUserList[i] })
            } else {
                addFlag = false
            }
            break
        }
    }
    for (let i = 0; i < userList.length; i++) {
        if (userList[i].userId === userId) {
            userList[i].isChecked = addFlag
            break
        }
    }
    if (!addFlag) {
        let i = 0
        for (; i < targetUserList.length; i++) {
            if (targetUserList[i].userId === userId) {
                break
            }
        }
        targetUserList.splice(i, 1)
    }
}

function searchAddUser(userId: string) {
    // 结果列表已存在
    for (let i = 0; i < targetUserList.length; i++) {
        if (targetUserList[i].userId === userId) {
            userSearchResList.length = 0
            return
        }
    }
    // 往结果列表加数据
    for (let i = 0; i < userSearchResList.length; i++) {
        if (userSearchResList[i].userId === userId) {
            userSearchResList[i].isChecked = true
            targetUserList.push({ ...userSearchResList[i] })
            break
        }
    }
    // 修改缓存数据列表数据
    for (let i = 0; i < userList.length; i++) {
        if (userList[i].userId === userId) {
            userList[i].isChecked = true
            break
        }
    }
    // 修改源列表数据
    for (let i = 0; i < sourceUserList.length; i++) {
        if (sourceUserList[i].userId === userId) {
            sourceUserList[i].isChecked = true
            break
        }
    }
    userSearchResList.length = 0
}

function removeUser(userId: string) {
    let i = 0;
    for (; i < targetUserList.length; i++) {
        if (targetUserList[i].userId === userId) {
            break
        }
    }
    targetUserList.splice(i, 1)

    for (let i = 0; i < userList.length; i++) {
        if (userList[i].userId === userId) {
            userList[i].isChecked = false
            break
        }
    }

    for (let i = 0; i < sourceUserList.length; i++) {
        if (sourceUserList[i].userId === userId) {
            sourceUserList[i].isChecked = false
            break
        }
    }
}

function submit() {
    const value: string[] = []
    for (let i = 0; i < targetUserList.length; i++) {
        value.push(targetUserList[i].userId)
    }
    emits("update:value", value)
    emits('cancel')
}

function userSearch(userName: string) {
    if (userName !== "") {
        if (timer) {
            clearTimeout(timer)
        }
        timer = setTimeout(() => {
            const request = {
                userName: userName
            }
            http.post("/user/list", request).then(({ data }) => {
                if (data.code === "0") {
                    userSearchResList.length = 0
                    for (let i = 0; i < data.data.length; i++) {
                        userSearchResList.push(data.data[i])
                        let flag = false
                        data.data[i].isChecked = false
                        for (let j = 0; j < userList.length; j++) {
                            if (userList[j].userId === data.data[i].userId) {
                                flag = true
                                break
                            }
                        }
                        if (!flag) {
                            userList.push(data.data[i])
                        }
                    }
                }
            })
        }, 500)
    } else {
        if (timer) {
            clearTimeout(timer)
        }
        userSearchResList.length = 0
    }
}

function getOrgUserInfo(orgCode: string) {
    const request = {
        orgCode: orgCode
    }
    http.post("/id/dept/user/list", request).then(({ data }) => {
        if (data.code === "0") {
            sourceUserList.length = 0
            for (let i = 0; i < data.data.length; i++) {
                let flag = false
                data.data[i].isChecked = false
                for (let j = 0; j < userList.length; j++) {
                    if (userList[j].userId === data.data[i].userId) {
                        flag = true
                        data.data[i].isChecked = userList[j].isChecked
                        break
                    }
                }
                if (!flag) {
                    userList.push(data.data[i])
                }
                sourceUserList.push(data.data[i])
            }
        }
    })
}

function initTargetUserList() {
    let reuqest: string[] = []
    if (props.value) {
        reuqest = props.value
    }
    http.post("/id/user/list", reuqest).then(({ data }) => {
        if (data.code === "0") {
            for (let i = 0; i < data.data.length; i++) {
                data.data[i].isChecked = true
                userList.push(data.data[i])
                targetUserList.push(data.data[i])
            }
        }
    })
}
</script>
<template>
    <n-card :title="props.title ? props.title : '人员选择'" closable @close="emits('cancel')" style="width: 850px;height:550px;"
        :header-style="{ padding: '12px 24px' }"
        :content-style="{ display: 'flex', flexDirection: 'column' }">
        <div style="display: flex;flex:1;">
            <div style="position: relative;flex:1;">
                <div class="head">
                    <n-input-group>
                        <n-input v-model:value="orgSearchPattern" placeholder="请输入部门名称" clearable />
                        <n-button style="width:35px" @click="orgStore.refreshOrgInfo()">
                            <template #icon>
                                <n-icon><reload-outlined /></n-icon>
                            </template>
                        </n-button>
                    </n-input-group>
                </div>
                <div class="content" style="border: 1px solid var(--n-border-color);">
                    <n-scrollbar style="max-height: 100%;" trigger="none" x-scrollable>
                        <n-tree :show-irrelevant-nodes="false" :node-props="treeNodeClicked" :pattern="orgSearchPattern"
                            :data="orgStore.orgInfoTree" block-line />
                    </n-scrollbar>
                </div>
            </div>
            <div
                :style="{ position: 'relative', flex: 2, '--flame-primary-color-transparent': configStore.themeColor.replace('rgb', 'rgba').replace(')', ', 0.1)') }">
                <div class="head">
                    <n-popover
                        :style="{ width: '500px', padding: 0, '--flame-primary-color-transparent': configStore.themeColor.replace('rgb', 'rgba').replace(')', ', 0.1)') }"
                        trigger="manual" placement="bottom" :show="userSearchResList.length > 0">
                        <template #trigger>
                            <n-input @input="userSearch" placeholder="请输入人员名称" clearable />
                        </template>
                        <div v-for="(user, index) in userSearchResList" :key="user.userId"
                            @click="searchAddUser(user.userId)" class="searchItem">
                            <div>{{ user.userName }}</div>
                            <div>{{ orgStore.getOrgName(user.orgCode) }}</div>
                        </div>
                    </n-popover>
                </div>
                <div class="content">
                    <div class="transfer">
                        <n-scrollbar style="max-height: 100%;" trigger="none" x-scrollable>
                            <div class="head">
                                <div>待选人员</div><n-button size="tiny" @click="selectAll">全选</n-button>
                            </div>
                            <div v-for="(user, index) in sourceUserList" :key="user.userId" class="checkbox-wrapper"
                                @click="sourceAddUser(user.userId)">
                                <n-checkbox :checked="user.isChecked">{{ user.userName }}</n-checkbox>
                            </div>
                        </n-scrollbar>
                    </div>
                    <div class="transfer">
                        <n-scrollbar style="max-height: 100%;" trigger="none" x-scrollable>
                            <div class="head">
                                <div>已选人员</div><n-button size="tiny" @click="clear">清空</n-button>
                            </div>
                            <div v-for="(user, index) in targetUserList" :key="user.userId">
                                <div class="target-wrapper" @click="removeUser(user.userId)">
                                    <div>{{ user.userName }}</div>
                                    <n-button size="tiny" quaternary @click="removeUser(user.userId)">
                                        <template #icon>
                                            <n-icon><close-outlined /></n-icon>
                                        </template>
                                    </n-button>
                                </div>
                            </div>
                        </n-scrollbar>
                    </div>
                </div>
            </div>
        </div>
        <slot></slot>
        <template #footer>
            <n-space justify="end">
                <n-button @click="emits('cancel')">取消</n-button>
                <n-button @click="submit" type="primary">确定</n-button>
            </n-space>
        </template>
    </n-card>
</template>
<style scoped>
.head {
    position: relative;
    display: flex;
    height: 34px;
    margin-bottom: 6px;
}

.content {
    position: absolute;
    top: 34px;
    bottom: 0;
    left: 0;
    right: 0;
    display: flex;
}

.transfer {
    flex: 1;
    max-height: 100%;
    border: 1px solid var(--n-border-color);
}

.transfer .head {
    padding: 6px 12px;
    display: flex;
    justify-content: space-between;
    height: 21px;
    margin: 0;
}

.transfer .checkbox-wrapper {
    padding: 6px 12px;
}

.transfer .checkbox-wrapper:hover {
    cursor: pointer;
    background-color: var(--flame-primary-color-transparent);
}

.transfer .target-wrapper {
    display: flex;
    justify-content: space-between;
    padding: 6px 12px;
}

.transfer .target-wrapper:hover {
    cursor: pointer;
    background-color: var(--flame-primary-color-transparent);
}

.searchItem {
    display: flex;
    justify-content: space-between;
    height: 36px;
    line-height: 36px;
    padding: 0 16px;
}

.searchItem:hover {
    cursor: pointer;
    background-color: var(--flame-primary-color-transparent);
}
</style>